//////////////////////////////////////////////////////////////////////////
// NO_Member
//////////////////////////////////////////////////////////////////////////
#ifndef	NO_MEMBER_H
#define NO_MEMBER_H

//////////////////////////////////////////////////////////////////////////
#include "NO_Includes.h"

//////////////////////////////////////////////////////////////////////////
class NO_Type;

//////////////////////////////////////////////////////////////////////////
// NO_IMember
//////////////////////////////////////////////////////////////////////////
class NO_DLL_TAL NO_IMember
{
public:
	//////////////////////////////////////////////////////////////////////////
	NO_IMember(std::string name);
	NO_IMember(const NO_Int8* name);
	virtual ~NO_IMember();

	//////////////////////////////////////////////////////////////////////////
			NO_UInt32			getID			(void)		const;
			const std::string&	getName			(void)		const;
	virtual const NO_Type&		getMemberType	(void)		const = 0;
	virtual const NO_Type&		getObjectType	(void)		const = 0;
	virtual NO_UInt32			getNummber		(void)		const = 0;
	virtual NO_Value*			getMember		(NO_Value&)	const = 0;

protected:
	//////////////////////////////////////////////////////////////////////////
	// friends
	//////////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////////
	friend class NO_Object;
	friend class NO_IArchive;	
	friend class NO_MemberFriend;

	//////////////////////////////////////////////////////////////////////////
	std::string name;

private:
	//////////////////////////////////////////////////////////////////////////
	NO_UInt32 id;
	NO_IMember* next;
};

//////////////////////////////////////////////////////////////////////////
// NO_Member
//////////////////////////////////////////////////////////////////////////
template<class M, class T>
class NO_Member : public NO_IMember
{
public:
	//////////////////////////////////////////////////////////////////////////
	typedef M T::*MT;

	//////////////////////////////////////////////////////////////////////////
	NO_Member(MT m, const NO_Int8 * n):NO_IMember(n),m(m){}

	//////////////////////////////////////////////////////////////////////////
	virtual const NO_Type&	getMemberType(void)	const {return NO_TypeID<M>::type();}
	virtual const NO_Type&	getObjectType(void)	const {return NO_TypeID<T>::type();}
	virtual NO_UInt32		getNummber(void)	const {return 1;}

	//////////////////////////////////////////////////////////////////////////
	virtual NO_Value*	getMember(NO_Value& obj) const
	{
		T* o = noGetDataException<T>(obj);
		NO_Value* v = new NO_ReferenceValue<M>(&(o->*m),&obj);
		v->setName(name);
		return v;
	}

private:
	//////////////////////////////////////////////////////////////////////////
	MT m;
};

//////////////////////////////////////////////////////////////////////////
// NO_RangeMember
//////////////////////////////////////////////////////////////////////////
template<class M, NO_UInt32 N, class T>
class NO_RangeMember : public NO_IMember
{
public:
	//////////////////////////////////////////////////////////////////////////
	typedef M (T::*RT)[N];
	typedef M (T::*MT);

	//////////////////////////////////////////////////////////////////////////
	NO_RangeMember(RT m, const NO_Int8* n):NO_IMember(n),m((MT)m){}

	//////////////////////////////////////////////////////////////////////////
	virtual const NO_Type&	getMemberType(void)	const {return NO_TypeID<M>::type();}
	virtual const NO_Type&	getObjectType(void)	const {return NO_TypeID<T>::type();}
	virtual NO_UInt32		getNummber(void)	const {return 1;}

	//////////////////////////////////////////////////////////////////////////
	virtual NO_Value*	getMember(NO_Value& obj) const
	{
		T* o = noGetDataException<T>(obj);
		NO_Value* v = new NO_ReferenceValue<M>(&(o->*m),&obj,N);
		v->setName(name);
		return v;
	}

private:
	//////////////////////////////////////////////////////////////////////////
	MT m;
};

//////////////////////////////////////////////////////////////////////////
// NO_Member
//////////////////////////////////////////////////////////////////////////
template<class T>
class NO_StaticMember : public NO_IMember
{
public:
	//////////////////////////////////////////////////////////////////////////
	typedef T* MT;
 
 	//////////////////////////////////////////////////////////////////////////
	NO_StaticMember(MT m, const NO_Int8* n):NO_IMember(n),m(m){}

	//////////////////////////////////////////////////////////////////////////
	virtual const NO_Type&	getMemberType(void)	const {return NO_TypeID<T>::type();}
	virtual const NO_Type&	getObjectType(void)	const {return NO_TypeID<void>::type();}
	virtual NO_UInt32		getNummber(void)	const {return 1;}

	//////////////////////////////////////////////////////////////////////////
	virtual NO_Value* getMember(NO_Value& obj)	const
	{
		NO_Value* v = new NO_ReferenceValue<T>(m,0);
		v->setName(name);
		return v;
	}

private:
	//////////////////////////////////////////////////////////////////////////
	MT m;
};

//////////////////////////////////////////////////////////////////////////
// NO_Member
//////////////////////////////////////////////////////////////////////////
template<class T, NO_UInt32 N>
class NO_StaticRangeMember : public NO_IMember
{
public:
 	//////////////////////////////////////////////////////////////////////////
	typedef T RT[N];
	typedef T* MT;

	//////////////////////////////////////////////////////////////////////////
	NO_StaticRangeMember(RT m, const NO_Int8* n):NO_IMember(n),m((MT)m){}

	//////////////////////////////////////////////////////////////////////////
	virtual const NO_Type&	getMemberType(void)	const {return NO_TypeID<T>::type();}
	virtual const NO_Type&	getObjectType(void)	const {return NO_TypeID<void>::type();}
	virtual NO_UInt32		getNummber(void)	const {return 1;}

	//////////////////////////////////////////////////////////////////////////
	virtual NO_Value*	getMember(NO_Value& obj) const
	{
		NO_Value* v = new NO_ReferenceValue<T>(m,0,N);
		v->setName(name);
		return v;
	}

private:
	//////////////////////////////////////////////////////////////////////////
	MT m;
};

//////////////////////////////////////////////////////////////////////////
// class NO_MemberFriend definition
//////////////////////////////////////////////////////////////////////////
class NO_DLL_TAL NO_MemberFriend  
{
protected:
	//////////////////////////////////////////////////////////////////////////
	NO_IMember* getNext	(const NO_IMember*)			const;
	void		setNext	(NO_IMember*, NO_IMember*)	const;
	void		setID	(NO_IMember*, NO_UInt32)	const;
};

//////////////////////////////////////////////////////////////////////////
// class NO_MemberList definition
//////////////////////////////////////////////////////////////////////////
class NO_DLL_TAL NO_MemberList  : public NO_MemberFriend
{
public:
	//////////////////////////////////////////////////////////////////////
	// con/destruction
	//////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////
	NO_MemberList(void);
	~NO_MemberList(void);
	
	//////////////////////////////////////////////////////////////////////////
	// modify
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	NO_Boolean addMember(NO_IMember*);
	
	//////////////////////////////////////////////////////////////////////////
	// retrieve
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	const NO_IMember* findMemberImpl(const NO_Int8* name)	const;
	const NO_IMember* findMemberImpl(NO_UInt32 ID)			const;

	//////////////////////////////////////////////////////////////////////////
	const NO_IMember* beginMemberImpl	(void) const;
	const NO_IMember* endMemberImpl		(void) const;
	const NO_IMember* nextMemberImpl	(const NO_IMember*) const;

private:
	//////////////////////////////////////////////////////////////////////
	NO_IMember* first;
	NO_IMember* last;
};

//////////////////////////////////////////////////////////////////////////
// class NO_MemberList definition
//////////////////////////////////////////////////////////////////////////
class NO_DLL_TAL NO_NoneMembers 
{
public:
	//////////////////////////////////////////////////////////////////////
	// con/destruction
	//////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////
	NO_NoneMembers(void);
	~NO_NoneMembers(void);
	
	//////////////////////////////////////////////////////////////////////////
	// retrieve
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	const NO_IMember* findMemberImpl(const NO_Int8* name)	const;
	const NO_IMember* findMemberImpl(NO_UInt32 ID)			const;

	//////////////////////////////////////////////////////////////////////////
	const NO_IMember * beginMemberImpl	(void) const;
	const NO_IMember * endMemberImpl	(void) const;
	const NO_IMember * nextMemberImpl	(const NO_IMember *) const;

};

#endif

